<?php
/**
 * This file is part of easycrm, created by PhpStorm.
 * Author: LouXin
 * Date: 2014/12/18 16:39
 * File: CustomValidator.php
 */

namespace Icsoc\DataBundle\Validator;

use Doctrine\DBAL\Connection;
use Symfony\Bridge\Monolog\Logger;

/**
 * Class CustomValidator
 *
 * @package Icsoc\DataBundle\Validator
 */
class CustomValidator
{
    /** @var Connection */
    private $conn;

    /** @var Logger */
    private $logger;

    /**
     * @param Connection $connection
     * @param Logger     $logger
     */
    public function __construct(Connection $connection, Logger $logger)
    {
        $this->conn = $connection;
        $this->logger = $logger;
    }

    /**
     * 判断角色是否属于该企业
     *
     * @param int $vccId  企业ID
     * @param int $roleId 角色ID
     *
     * @return bool
     */
    public function checkIfRoleBelongsToVcc($vccId, $roleId)
    {
        $vid = $this->conn->fetchColumn(
            'SELECT vcc_id FROM cc_roles WHERE role_id = :role_id',
            array('role_id' => $roleId)
        );

        if ($vccId != $vid) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 验证 企业代码
     *
     * @param string $value
     *
     * @return array|string
     */
    public function checkVccCode($value = '')
    {

        if (empty($value)) {
            $ret = array(
                'code' => 401,
                'message' => '企业账号为空',
            );

            return $ret;
        }

        $vccId = $this->conn->fetchColumn(
            " SELECT vcc_id FROM cc_ccods WHERE vcc_code = :vcc_code LIMIT 1 ",
            array('vcc_code' => $value)
        );

        if (empty($vccId)) {
            $ret = array(
                'code' => 402,
                'message' => '企业账号错误',
            );

            return $ret;
            //return new JsonResponse($ret);
        }

        return $vccId;
    }

    /**
     * 检查是否为 json
     *
     * @param string $info
     *
     * @return array|mixed
     */
    public function checkJson($info)
    {
        $addInfo = array();
        if (!empty($info)) {
            $addInfo = json_decode($info, true);
            if (json_last_error()) {
                return array('code' => 403, 'message' => 'info格式非json');
            }
        }

        return $addInfo;
    }

    /**
     * 验证技能组 是否属于该企业
     *
     * @param int    $vccId
     * @param int    $queId
     * @param string $code
     *
     * @return array|string
     */
    public function vccQue($vccId, $queId, $code = '404')
    {
        //验证技能组id 是否属于该企业；
        $vid = $this->conn->fetchColumn(
            'SELECT vcc_id FROM win_queue WHERE id = :que_id AND is_del = 0',
            array('que_id' => $queId)
        );
        //判断节能组是否属于该企业
        if ($vccId != $vid) {
            $ret = array(
                'code' => $code,
                'message' => '技能组不属于该企业',
            );

            return $ret;
        }

        return '';
    }

    /**
     * 技能组名称重复
     *
     * @param string $where
     * @param string $parArr
     * @param string $code
     *
     * @return array|string
     */
    public function existQue($where, $parArr, $code = '405')
    {
        $count = $this->conn->fetchColumn(
            'SELECT count(*) FROM win_queue WHERE '.$where,
            $parArr
        );
        if ($count > 0) {
            $ret = array(
                'code' => $code,
                'message' => '技能组已经存在',
            );

            return $ret;
        }

        return '';
    }

    /**
     * 重载技能组
     *
     * @param int    $vccId
     * @param string $address
     * @param string $port
     * @param string $code
     *
     * @return array
     *
     */
    public function wintelsReload($vccId, $address, $port = '5015', $code = '416')
    {
        $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        if ($socket === false) {
            $errorCode = socket_last_error();
            $errorMsg = socket_strerror($errorCode);
            $this->logger->warning('无法创建socket：['.$errorCode.']'.$errorMsg);
            $ret = array(
                'code' => $code,
                'message' => '重载失败 [ 无法创建socket:'.$errorCode.$errorMsg.']',
            );

            return $ret;
        }
        $res = @socket_connect($socket, $address, $port);
        //连接失败
        if ($res === false) {
            $errorCode = socket_last_error();
            $errorMsg = socket_strerror($errorCode);
            $this->logger->warning('socket无法连接到['.$address.':'.$port.']：['.$errorCode.']'.$errorMsg);
            $ret = array(
                'code' => $code,
                'message' => '重载失败 [socket无法连接到:'.$errorCode.$errorMsg.']',
            );

            return $ret;
        }
        $str = "reload queue $vccId\r\n\r\n";
        $res = @socket_write($socket, $str, strlen($str));
        if ($res === false) {
            $errorCode = socket_last_error();
            $errorMsg = socket_strerror($errorCode);
            $this->logger->warning('socket发送数据失败：['.$errorCode.']'.$errorMsg);
            $ret = array(
                'code' => $code,
                'message' => '重载失败 [socket发送数据失败:'.$errorCode.$errorMsg.']',
            );

            return $ret;
        }
        $responce = @socket_read($socket, 100);
        if (strstr($responce, 'Success')) {
            //记录 成功一个
            $ret = array(
                'code' => 200,
                'message' => 'ok',
            );

            return $ret;
        } else {
            //如果出现无法连接服务器
            $errorCode = socket_last_error();
            $errorMsg = socket_strerror($errorCode);
            $this->logger->warning('socket读取数据失败：['.$errorCode.']'.$errorMsg);
            $ret = array(
                'code' => $code,
                'message' => '重载失败 [socket读取数据失败:'.$errorCode.$errorMsg.']',
            );

            return $ret;
        }
    }

    /**
     * @param string $value
     * @param string $code
     * @param string $msg
     *
     * @return array|string
     * 验证名称是否为空,默認是技能組
     */
    public function isEmptyName($value = '', $code = '403', $msg = '技能组名称为空')
    {
        if (empty($value)) {
            $ret = array(
                'code' => $code,
                'message' => $msg,
            );

            return $ret;
        }

        return '';
    }

    /**
     * 重载坐席
     *
     * @param string  $vccId   企业id
     * @param string  $address 中间件地址
     * @param integer $agId    坐席id
     * @param string  $port    端口
     * @param string  $code    错误代码
     *
     * @return array
     */
    public function reloadAgent($vccId, $address, $agId, $port = '5015', $code = '416')
    {
        $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        if ($socket === false) {
            $errorCode = socket_last_error();
            $errorMsg = socket_strerror($errorCode);
            $this->logger->warning($vccId.' '.$agId.' 无法创建socket：['.$errorCode.']'.$errorMsg);
            $ret = array(
                'code' => $code,
                'message' => '重载失败 [ 无法创建socket:'.$errorCode.$errorMsg.']',
            );

            return $ret;
        }
        $res = @socket_connect($socket, $address, $port);
        //连接失败
        if ($res === false) {
            $errorCode = socket_last_error();
            $errorMsg = socket_strerror($errorCode);
            $this->logger->warning($vccId.' '.$agId.'socket无法连接到['.$address.':'.$port.']：['.$errorCode.']'.$errorMsg);
            $ret = array(
                'code' => $code,
                'message' => '重载失败 [socket无法连接到:'.$errorCode.$errorMsg.']',
            );

            return $ret;
        }
        $str = "agreload($agId)";
        $str .= "\r\n\r\n";
        $res = @socket_write($socket, $str, strlen($str));
        if ($res === false) {
            $errorCode = socket_last_error();
            $errorMsg = socket_strerror($errorCode);
            $this->logger->warning($vccId.' '.$agId.'socket发送数据失败：['.$errorCode.']'.$errorMsg);
            $ret = array(
                'code' => $code,
                'message' => '重载失败 [socket发送数据失败:'.$errorCode.$errorMsg.']',
            );

            return $ret;
        }
        $responce = @socket_read($socket, 100);
        if (strstr($responce, 'Success')) {
            //记录 成功一个
            $ret = array(
                'code' => 200,
                'message' => 'ok',
            );

            return $ret;
        } elseif ($responce === false) {
            //如果出现无法连接服务器
            $errorCode = socket_last_error();
            $errorMsg = socket_strerror($errorCode);
            $this->logger->warning($vccId.' '.$agId.'$vcc_id $agId, socket读取数据失败：['.$errorCode.']'.$errorMsg);
            $ret = array(
                'code' => $code,
                'message' => '重载失败 [socket读取数据失败:'.$errorCode.$errorMsg.']',
            );

            return $ret;
        } else {
            $errname = $responce;
            $fail = true;
            $responce = explode("\r\n", $responce);
            if (isset($responce[1])) {
                $errcode = explode(":", $responce[1]);
                if (isset($errcode[1])) {
                    switch (trim($errcode[1])) {
                        case '1':
                            $errname = "坐席不存在，可忽略，可能没有登录";
                            $fail = false; //这个失败可忽略；
                            break;
                        case '2':
                            $errname = "URL错误";
                            break;
                        case '3':
                            $errname = "调用HTTP接口失败";
                            break;
                        case '4':
                            $errname = "返回格式不对";
                            break;
                        case '5':
                            $errname = "返回格式不对";
                            break;
                        case '6':
                            $errname = "接口返回错误,比如在数据库中找不到坐席";
                            break;
                        case '7':
                            $errname = "有队列不存在";
                            break;
                        default:
                            $errname = "格式错误";
                            break;
                    }
                }
                $strs = "$vccId $agId reload agent error: [$errcode[1]] $errname";
                $this->logger->warning($strs);

                return array('code' => $code, 'message' => $errname, 'fail' => $fail);
            } else {
                $errname = '中间件返回格式不正确';
                $this->logger->warning($errname);

                return array('code' => $code, 'message' => $errname);
            }
        }
    }

    /**
     * 重载中间件
     *
     * @param int    $vccId
     * @param string $winip
     *
     * @return bool
     */
    public function reloadVcc($vccId, $winip)
    {
        $port = "5015";
        $socket = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        if ($socket === false) {
            $errorcode = socket_last_error();
            $errormsg = socket_strerror($errorcode);
            $strs = "$vccId reload vcc socket_create() failed: [$errorcode] $errormsg";
            $this->logger->warning($strs);

            return false;
        }

        @socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 3, "usec" => 0));
        @socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array("sec" => 3, "usec" => 0));

        $res = @socket_connect($socket, $winip, $port);
        if ($res === false) {
            $errorcode = socket_last_error();
            $errormsg = socket_strerror($errorcode);
            $strs = "$vccId reload vcc socket_connect() failed: [$errorcode] $errormsg";
            $this->logger->warning($strs);

            return false;
        }

        $str = "reload vcc $vccId\r\n\r\n";
        $res = @socket_write($socket, $str, strlen($str));
        if ($res === false) {
            $errorcode = socket_last_error();
            $errormsg = socket_strerror($errorcode);
            $strs = "$vccId reload vcc socket_write() failed: [$errorcode] $errormsg";
            $this->logger->warning($strs);

            return false;
        }

        $responce = @socket_read($socket, 100);
        if ($responce === false) {
            $errorcode = socket_last_error();
            $errormsg = socket_strerror($errorcode);
            $strs = "$vccId reload vcc socket_read() failed: [$errorcode] $errormsg";
            $this->logger->warning($strs);

            return false;
        }

        return strstr($responce, 'Success') ? true : false;
    }

    /**
     * 判断一个坐席是否属于某一个企业的；
     *
     * @param int $vccId
     * @param int $userId
     *
     * @return bool
     */
    public function agentExist($vccId, $userId)
    {
        $count = $this->conn->fetchColumn(
            'SELECT count(*) FROM win_agent WHERE vcc_id = :vcc_id AND id = :user_id AND is_del = 0',
            array('vcc_id' => $vccId, 'user_id' => $userId)
        );

        return $count ? true : false;
    }


    /**
     * 验证角色是否已经存在
     *
     * @param string $where
     * @param string $parArr
     * @param string $code
     *
     * @return array|string
     */
    public function existRole($where, $parArr, $code = '405')
    {
        $count = $this->conn->fetchColumn(
            'SELECT count(*) FROM cc_roles WHERE '.$where,
            $parArr
        );
        if ($count > 0) {
            $ret = array(
                'code' => $code,
                'message' => '角色已经存在',
            );

            return $ret;
        }

        return '';
    }

    /**
     * 验证角色是否属于该企业
     *
     * @param int    $vccId  企业ID
     * @param int    $roleId 角色ID
     * @param string $code   错误编码
     *
     * @return array|string
     */
    public function checkRoleIfBelongsToVcc($vccId, $roleId, $code = '404')
    {
        //验证角色id 是否属于该企业；
        $vid = $this->conn->fetchColumn(
            'SELECT vcc_id FROM cc_roles WHERE role_id = :role_id',
            array('role_id' => $roleId)
        );
        if ($vccId != $vid) {
            $ret = array(
                'code' => $code,
                'message' => '角色不属于该企业',
            );

            return $ret;
        }

        return '';
    }
}
